package basic;

//线程阻塞和线程通信
//通过消费者和生产者问题举例
//存钱和取钱操作不能同时进行

class Acount{

    private String name;
    private double balance;
    private boolean flag=true;//信号量：true==>allow put;false===>allow take

    public Acount(String name,double balance){
        
        this.balance=balance;
        this.name=name;
    }


    /**
     * 存钱操作
     * @param money
     */
    public synchronized void put(double money,int i){

        if(!flag){
            try {
                System.out.println(Thread.currentThread().getName()+"存钱失败");
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{

            this.balance+=money;
            System.out.println(Thread.currentThread().getName()+"第"+i+"次存钱"+money);
            System.out.println("当前余额为:"+this.balance);
            flag=false;
            notifyAll();
        }
    }
    /**
     * 取钱操作
     * @param money
     */
    public synchronized void take(double money,int i) {
        
        if(flag){

            try {
                System.out.println(Thread.currentThread().getName()+"取钱失败");
                wait();
                
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return;
        }
            if(this.balance<money){
                //interrupted
                try {
                    System.out.println(Thread.currentThread().getName()+"取钱失败");
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return;
            }

            this.balance-=money;
            System.out.println(Thread.currentThread().getName()+"第"+i+"次取钱"+money);
            System.out.println("当前余额为："+this.balance);
            flag=true;
            notifyAll();


    }
}


class PutThread extends Thread{

    private Acount acount;
    private String name;
    private double money;

    public  PutThread(Acount acount,String name,double money) {
        super(name);
        this.acount=acount;
        this.money=money;
    }

    @Override
    public void run() {
        
        for (int i = 0; i < 100; i++) {
            acount.put(money,i);
        }
    }
}

class TakeThread extends Thread{

    private Acount acount;
    private String name;
    private double money;

    public  TakeThread(Acount acount,String name,double money) {
        super(name);
        this.acount=acount;
        this.money=money;
    }

    @Override
    public void run() {
        
        for (int i = 0; i < 100; i++) {
            acount.take(money,i);
            
        }
    }
}
public class ThreadComunication {
    

    public static void main(String[] args) {
        Acount acount= new Acount("name",0);
        new PutThread(acount, "liulong", 123).start();
        new PutThread(acount, "long", 123).start();
        new TakeThread(acount, "liu", 123).start(); 
        new TakeThread(acount, "ll", 123).start();

    }
}
